package com.msmall.community.weather.service.impl;

import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;

import com.msmall.base.cache.CacheFactory;
import com.msmall.base.util.Constants;
import com.msmall.community.common.model.City;
import com.msmall.community.common.service.CityManager;
import com.msmall.community.weather.model.Weather;
import com.msmall.community.weather.model.WeatherPaser;
import com.msmall.community.weather.service.WeatherManager;

public class WeatherManagerImpl implements WeatherManager{
	
	private static final Log logger = LogFactory.getLog(WeatherManagerImpl.class);
	
	public static String DEFAULT_URL = "http://www.google.com/ig/api?hl=zh-cn&weather=";
	
	private CityManager cityManager;
	
	public void setCityManager(CityManager cityManager) {
		this.cityManager = cityManager;
	}
	/**
	 * @param cityCode行政区划码
	 */
	public Weather getWeather(String cityCode) throws Exception{
		if(cityCode == null || "".equals(cityCode))
			cityCode = WeatherManager.DEFAULT_WEATHER_CODE;
		
		Weather weather = getCacheWeather(cityCode, false); // 非强制从缓存读取
		if(weather != null)
			return weather;
		
		City city = null;
		String weatherCity = WeatherManager.DEFAULT_WEATHER_PINGY;
		try{
			city = cityManager.getCityByCode(cityCode);
			weatherCity = null;//city.getWeatherCode(); TODO
		}catch(Exception e){
			throw new Exception("city not found with code :"+ cityCode);
		}
		HttpClient httpClient = new DefaultHttpClient();
		try {
			HttpGet httpget = new HttpGet(DEFAULT_URL + weatherCity);
			ResponseHandler<String> responseHandler = new BasicResponseHandler();
		    String responseBody = httpClient.execute(httpget, responseHandler);
		    try{
		    	weather = WeatherPaser.parser(responseBody);
		    }catch(Exception e){
		    	weather = getCacheWeather(cityCode, true);
		    	if(weather != null)
					return weather;
		    }
		    weather.setCityCode(cityCode);
		    weather.setName(city.getFullName());
		    weather.setLastDate(new Date());
		    cacheWeather(weather);
		    return weather;
		} catch (ClientProtocolException e) {
			logger.error(e);
			throw e;
		} catch (IOException e) {
			logger.error(e);
			throw e;
		} catch (Exception e) {
			logger.error(e);
			throw e;
		} finally{
			httpClient.getConnectionManager().shutdown();
		}
	}
	public void cacheWeather(Weather weather){
		Map map = (Map)CacheFactory.getInstance().getCache(Constants.CACHE_NAME_COMMON).get(Constants.CACHE_KEY_WEATHER_MAP);
		if(null == map){
			map = new HashMap();
			CacheFactory.getInstance().getCache(Constants.CACHE_NAME_COMMON).put(Constants.CACHE_KEY_WEATHER_MAP,map);
		}
		map.put(weather.getCityCode(), weather);
	}
	/**
	 * force: 如果为true则不管是不是数据过期，都从CACHE中获得
	 * @param cityCode 行政区划码
	 * @param tag
	 * @return
	 */
	public Weather getCacheWeather(String cityCode, boolean force){
		try{
			Map map = (Map)CacheFactory.getInstance().getCache(Constants.CACHE_NAME_COMMON).get(Constants.CACHE_KEY_WEATHER_MAP);
			if(null == map || map.isEmpty()){
				return null;
			}else{
				Weather weather = (Weather) map.get(cityCode);
				if(weather == null)
					return null;
				if(force)
					return weather;
				if(newRequest(weather.getLastDate()))
					return null;
				else
					return weather;
			}
		}catch(Exception e){
			return null;
		}
	}
	/**
	 * 是否需要从GOOGLE重新请求
	 * @param lastDate
	 * @return
	 */
	private boolean newRequest(Date lastDate){
		long oneHour = 1000*60*60*1;
		long lastl = lastDate.getTime();
		long nowl = Calendar.getInstance().getTimeInMillis();
		long cha = nowl - lastl;
		if(cha > oneHour)
			return true; //需要重新请求
		if(isSameDate(lastDate, new Date())){ //在第二天的第一个小时， 和第一天的最后一个小时起效
			return false;
		}else{
			return true;
		}
	}
	public Weather getWeather(String city, Date date){
		return null;
	}
	
	/**
	 * 每隔一个小时更新缓存的天气信息
	 */
	@Deprecated
	public void refreshWeatherCache(){
		Map map = (Map)CacheFactory.getInstance().getCache(Constants.CACHE_NAME_COMMON).get(Constants.CACHE_KEY_WEATHER_MAP);
		if(null != map && !map.isEmpty()){
			Iterator it = map.keySet().iterator();
			while(it.hasNext()){
				String city = (String) it.next();
				map.remove(city);
				try {
					Weather weather = getWeather(city);
				//	map.put(city.toLowerCase(), weather);
				} catch (Exception e) {
				}
			}
		}
	}
	/**
	 * 比较2个日期是不是同一天
	 * @param one
	 * @param two
	 * @return
	 */
	private static boolean isSameDate(Date one, Date two){
		try{
			long oneDay = 1*24*60*60*1000;
			long onel = one.getTime();
			long twol = two.getTime();
			long cha = Math.abs(onel - twol);
			if(cha < oneDay)
				return true;
			return false;
		}catch(Exception e){
			return false;
		}
	}
}
